
use std::ops::Mul;
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug,Serialize, Deserialize )]
pub struct ErrorResp {
    pub code:Option<String>,
    pub message:Option<String>,
    pub detail:Option<ErrorTraceResp>,

}

#[derive(Clone, Debug,Serialize, Deserialize )]
pub struct ErrorTraceResp {
    pub field: Option<String>,
    pub value: Option<String>,
    pub issue: Option<String>,
    pub location :Option<String>
}

#[derive(Clone, Debug,Serialize, Deserialize )]
pub struct Amount {
    pub total: Option<i32>,
    pub currency: Option<String>,
    pub payer_total:Option<i32>,
    pub payer_currency:Option<String>,
}

///
/// 这里应该有BUG，数值太大，导致数据溢出
/// 是否需要判断数据的大小？
impl Amount {
    pub fn new(amount: f64) -> Self {
        let t = amount.mul(100.0) as i32;
        Amount {
            total: Some(t),
            currency: Some("CNY".to_owned()),
            payer_total:None,
            payer_currency:None,
        }
    }
}



#[derive(Clone, Debug,Serialize, Deserialize )]
pub struct Payer {
    pub openid: String,
}



#[derive(Clone, Debug,Serialize, Deserialize )]
pub struct RequestOrder {
    pub appid: String,
    pub mchid: String,
    pub description: String,
    pub out_trade_no: String,
    pub time_expire: Option<String>,
    pub attach: Option<String>,
    pub notify_url: Option<String>,
    pub goods_tag: Option<String>,
    pub amount:Amount,
    pub payer:Payer,
    pub detail:Option<DetailInfo>,
    pub scene_info:Option<SceneInfo>,
    pub settle_info:Option<SettleInfo>,
    
}

#[derive(Clone, Debug,Serialize, Deserialize )]
pub struct RequestOrderResp {
    pub prepay_id: String,
}



#[derive(Clone, Debug,Serialize, Deserialize )]
pub struct SettleInfo {
    pub profit_sharing: bool,
}


#[derive(Clone, Debug,Serialize, Deserialize )]
pub struct StoreInfo {
    pub id: String,
    pub name:Option<String>,
    pub area_code:Option<String>,
    pub address:Option<String>,
}


#[derive(Clone, Debug,Serialize, Deserialize )]
pub struct SceneInfo {
    pub payer_client_ip: Option<String>,
    pub device_id:Option<String>,
    pub store_info:Option<StoreInfo>,
}
 

#[derive(Clone, Debug,Serialize, Deserialize )]
pub struct GoodsInfo {
    pub merchant_goods_id: String,
    pub wechatpay_goods_id:Option<String>,
    pub goods_name:Option<String>,
    pub quantity:Option<i32>,
    pub unit_price:Option<i32>,
}

#[derive(Clone, Debug,Serialize, Deserialize )]
pub struct DetailInfo {
    pub goods_detail:Option<Vec<GoodsInfo>>,
    pub cost_price:Option<i32>,
    pub invoice_id:Option<String>,
}


#[derive(Clone, Debug,Serialize, Deserialize )]
pub struct PromotionGoodsInfo {
    pub goods_id:String,
    pub discount_amount :i32,
    pub quantity:i32,
    pub unit_price:i32,
    pub goods_remark:Option<String>,
}


#[derive(Clone, Debug,Serialize, Deserialize )]
pub struct Promotion {
    pub coupon_id:Option<String>,
    pub name:Option<String>,
    pub scope:Option<String>,
    #[serde(rename = "type")]
    pub p_type:Option<String>,
    pub amount :i32,
    pub stock_id:Option<String>,
    pub wechatpay_contribute :Option<i32>,
    pub merchant_contribute :Option<i32>,
    pub other_contribute :Option<i32>,
    pub currency:Option<String>, 
    pub goods_detail:Option<Vec<PromotionGoodsInfo>>, 
}

 

#[derive(Clone, Debug,Serialize, Deserialize )]
pub struct PaymentOrder {
    pub appid: String,
    pub mchid: String,
    pub out_trade_no: String,
    pub transaction_id: Option<String>,
    pub trade_type: Option<String>,
    pub trade_state: Option<String>,
    pub trade_state_desc: Option<String>,
    pub bank_type: Option<String>,
    pub attach: Option<String>,
    pub success_time: Option<String>,
    pub payer:Payer,
    pub amount:Option<Amount>,
    pub goods_tag: Option<String>,
    pub scene_info:Option<SceneInfo>,
    pub promotion_detail:Option<Vec<Promotion>>,
}



#[derive(Clone, Debug,Serialize, Deserialize )]
pub struct RequestRefund {
    pub transaction_id: Option<String>,
    pub out_trade_no: Option<String>,
    pub out_refund_no: Option<String>,
    pub reason: String,
    pub notify_url: Option<String>,
    pub funds_account: Option<String>,
    pub amount:RefundAmount,
    pub goods_detail:Option<Vec<RefundGoodsInfo>>,
    
}


#[derive(Clone, Debug,Serialize, Deserialize )]
pub struct RefundAmount {
    pub refund: i32,
    pub total: Option<i32>,
    pub currency: Option<String>,
    pub from:Option<Vec<RefundAmountFrom>>
}
 

#[derive(Clone, Debug,Serialize, Deserialize )]
pub struct RefundAmountFrom {
    pub amount: i32,
    pub account: String,
}


#[derive(Clone, Debug,Serialize, Deserialize )]
pub struct RefundGoodsInfo {
    pub merchant_goods_id: String,
    pub wechatpay_goods_id:Option<String>,
    pub goods_name:Option<String>,
    pub unit_price:i32,
    pub refund_amount:i32,
    pub refund_quantity:i32,
}



#[derive(Clone, Debug,Serialize, Deserialize )]
pub struct RefundResp {
    pub refund_id:String,
    pub out_refund_no: Option<String>,
    pub transaction_id: Option<String>,
    pub out_trade_no: Option<String>,
    pub channel:String,
    pub user_received_account: String,
    pub success_time: Option<String>,
    pub create_time: Option<String>,
    pub status: String,
    pub funds_account: Option<String>,
    pub amount:RefundRespAmount,
    pub promotion_detail:Option<Vec<RefundPromotion>>, 
}


#[derive(Clone, Debug,Serialize, Deserialize )]
pub struct RefundRespAmount {
    pub refund: i32,
    pub total: i32,
    pub currency: Option<String>,
    pub from:Option<Vec<RefundAmountFrom>>,
    pub payer_refund:i32,
    pub settlement_refund:i32,
    pub settlement_total:i32,
    pub discount_refund:i32,
}


#[derive(Clone, Debug,Serialize, Deserialize )]
pub struct RefundPromotion {
    pub promotion_id:String,
    pub scope:Option<String>,
    #[serde(rename = "type")]
    pub p_type:Option<String>,
    pub amount :i32,
    pub refund_amount :i32,
    pub goods_detail:Option<Vec<RefundGoodsInfo>>, 
}
